﻿using System;
using System.Collections.Generic;
using NLite.Mini.Activation;
using NLite.Mini.Context;

namespace NLite.Mini.Lifestyle
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TLifestyleManager"></typeparam>
    [Serializable]
    public class GenericLifestyleManager<TLifestyleManager> : ILifestyleManager where TLifestyleManager : ILifestyleManager, new()
    {
        /// <summary>
        /// 
        /// </summary>
        protected IDictionary<int, TLifestyleManager> cache = new Dictionary<int, TLifestyleManager>();

        #region ILifestyleManager Members
        /// <summary>
        /// 
        /// </summary>
        public IKernel Kernel { get; private set; }
        /// <summary>
        /// 
        /// </summary>
        public IActivator Activator { get; private set; }
        /// <summary>
        /// 
        /// </summary>
        public IComponentInfo Info { get; private set; }
        /// <summary>
        /// 
        /// </summary>
        public Action<IComponentInfo, object> OnDestroying { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="activator"></param>
        /// <param name="kernel"></param>
        /// <param name="info"></param>
        /// <param name="onDestroyed"></param>
        public virtual void Init(IActivator activator, IKernel kernel, IComponentInfo info, Action<IComponentInfo, object> onDestroyed)
        {
            this.Activator = activator;
            this.Kernel = kernel;
            this.Info = info;
            OnDestroying = onDestroyed;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public virtual object Get(IPreCreationContext ctx)
        {
            int key = 123;
            foreach (var item in ctx.GenericParameters)
                key = key ^ item.TypeHandle.Value.GetHashCode();

            if (!cache.ContainsKey(key))
            {
                var lifestyleMgr = new TLifestyleManager();
                lifestyleMgr.Init(Activator, ctx.Kernel, ctx.Component, OnDestroying);
                cache[key] = lifestyleMgr;
            }

            return cache[key].Get(ctx);
        }


        #endregion

        #region IDisposable Members

        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            foreach (var item in cache.Values)
                item.Dispose();
        }

        #endregion
    }
}
